﻿using System;
using System.Collections;
using UnityEngine;
using Object = UnityEngine.Object;

namespace winS.Unity
{
    /// <summary>
    /// 协程启动器
    /// </summary>
    public static class CoroutineStarter
    {
        private static readonly CoroutineUpdater coroutineUpdater;

        static CoroutineStarter()
        {
            GameObject updaterGameObject = new GameObject("Coroutine Updater") { hideFlags = HideFlags.HideInHierarchy };
            coroutineUpdater = updaterGameObject.AddComponent<CoroutineUpdater>();
            Object.DontDestroyOnLoad(updaterGameObject);
        }

        /// <summary>
        /// 启动指定的 <see cref="IEnumerator"/> 协程
        /// </summary>
        public static Coroutine Start(IEnumerator enumerator)
        {
            return StartWithName(enumerator, null);
        }
        /// <summary>
        /// 启动指定的 <see cref="IEnumerator"/> 协程并指定所有者
        /// </summary>
        public static Coroutine Start(IEnumerator enumerator, GameObject owner)
        {
            if (!owner.activeInHierarchy) throw new Exception($"[{nameof(CoroutineStarter)}.{nameof(Start)}] 协程所有者必须处于完全激活状态才可以启动协程");
            if (!owner.TryGetComponent(out CoroutineOwner coroutineOwner)) coroutineOwner = owner.AddComponent<CoroutineOwner>();
            Coroutine coroutine = Start(enumerator);
            coroutineOwner.AddCoroutine(coroutine);
            return coroutine;
        }

        /// <summary>
        /// 启动带有 <see cref="IEnumerator"/> 返回值的协程函数
        /// </summary>
        public static Coroutine Start(Func<IEnumerator> enumeratorFunction)
        {
            return Start(enumeratorFunction());
        }
        /// <summary>
        /// 启动带有 <see cref="IEnumerator"/> 返回值的协程函数并指定所有者
        /// </summary>
        public static Coroutine Start(Func<IEnumerator> enumeratorFunction, GameObject owner)
        {
            return Start(enumeratorFunction(), owner);
        }

        /// <summary>
        /// 启动指定的 <see cref="IEnumerator"/> 协程
        /// </summary>
        public static Coroutine StartWithName(IEnumerator enumerator, string name)
        {
            CoroutineCore coroutineCore = CoroutineCorePool.Pop(enumerator);
            coroutineCore.name = name;
            Coroutine coroutine = new Coroutine(coroutineCore);
            Add(coroutineCore);
            return coroutine;
        }
        /// <summary>
        /// 启动带有 <see cref="IEnumerator"/> 返回值的协程函数
        /// </summary>
        public static Coroutine StartWithName(Func<IEnumerator> enumeratorFunction, string name)
        {
            return StartWithName(enumeratorFunction(), name);
        }

        internal static void Add(CoroutineCore coroutineCore)
        {
            coroutineUpdater.AddCoroutineCore(coroutineCore);
        }
        internal static void Remove(CoroutineCore coroutineCore)
        {
            coroutineUpdater.RemoveCoroutineCore(coroutineCore);
        }
    }
}